package com.iteaj.iot.taos;

import com.iteaj.iot.tools.annotation.IotField;
import com.iteaj.iot.tools.annotation.IotFieldMeta;
import com.iteaj.iot.tools.annotation.IotTag;
import com.iteaj.iot.tools.annotation.IotTagMeta;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class EntityMetas {

    private STable sTable;

    private String insertSql;

    private String paramSql;

    private Class<?> entityClass;

    private TagsResolver tagsResolver;

    private List<IotTagMeta> tags = new ArrayList<>();

    private List<IotFieldMeta> fields = new ArrayList<>();


    public EntityMetas(Class<?> entityClass) {
        this.entityClass = entityClass;
    }

    protected EntityMetas resolve() {
        this.sTable = entityClass.getAnnotation(STable.class);
        if(this.sTable == null) return null;

        Field[] declaredFields = entityClass.getDeclaredFields();
        for(Field item : declaredFields) {
            IotTag tag = item.getAnnotation(IotTag.class);
            if(tag != null) {
                tags.add(new IotTagMeta(Objects.equals(tag.value(), "") ? item.getName() : tag.value(), tag, item));
            }

            IotField field = item.getAnnotation(IotField.class);
            if(field != null) {
                IotFieldMeta meta = new IotFieldMeta(field, Objects.equals(field.value(), "") ? item.getName() : field.value(), item);
                fields.add(meta);
            }

            if(tag != null && field != null) {
                throw new TaosException("字段["+item.getName()+"]不能同时使用注解[IotTag and IotField]");
            }
        }

        this.paramSql = "("+this.fields.stream().map(item -> "?").collect(Collectors.joining(","))+")";
        this.insertSql = "insert into "+this.sTable.table()+" (" + this.fields.stream().map(item -> item.getName()).collect(Collectors.joining(","))+") values ";
        return this;
    }

    public SqlParameterValue[] getParams(Object entity) {
        SqlParameterValue[] parameterValue = new SqlParameterValue[this.fields.size()];

        for (int i=0; i<this.fields.size(); i++) {
            Object value = ReflectionUtils.getField(this.fields.get(i).getField(), entity);
            parameterValue[i] = new SqlParameterValue(0, value);
        }

        return parameterValue;
    }

    public String getInsertSql() {
        return insertSql;
    }

    public String getParamSql() {
        return paramSql;
    }

    public Class<?> getEntityClass() {
        return entityClass;
    }
}
